"""
认证中间件
全局 Token 验证，白名单内的接口无需认证
"""
from fastapi import Request, status
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
from utils.auth import verify_token


class AuthMiddleware(BaseHTTPMiddleware):
    """
    全局认证中间件

    白名单内的路径无需 Token 验证
    其他所有路径都需要携带有效的 Token
    """

    # 白名单：无需 Token 验证的路径
    WHITELIST = [
        "/",                              # 根路径
        "/docs",                          # Swagger 文档
        "/redoc",                         # ReDoc 文档
        "/openapi.json",                  # OpenAPI schema
        "/users/login",                   # 登录
        "/users/register",                # 注册
        "/users/dingtalklogin",           # 钉钉登录
        "/users/dingtalkcallback",        # 钉钉回调
        "/users/refresh",                 # 刷新 Token
        "/indiv/push",                    # 手动推送测试接口（去掉末尾斜杠）
    ]

    async def dispatch(self, request: Request, call_next):
        """
        处理每个请求

        Args:
            request: 请求对象
            call_next: 下一个处理函数

        Returns:
            响应对象
        """
        # CORS 预检请求（OPTIONS）直接放行
        if request.method == "OPTIONS":
            response = await call_next(request)
            return response

        # 获取请求路径（去掉末尾的斜杠，统一格式）
        path = request.url.path.rstrip('/')
        if path == '':  # 根路径特殊处理
            path = '/'
        print(f"🔒 AuthMiddleware - 请求路径: {path}")

        # 检查是否在白名单中
        if path in self.WHITELIST:
            print(f"✅ 白名单路径，放行: {path}")
            # 白名单路径，直接放行
            response = await call_next(request)
            return response

        # 特殊处理 WebSocket 连接（不区分大小写）
        upgrade_header = request.headers.get("upgrade", "").lower()
        if upgrade_header == "websocket" or path.startswith("/ws") or path.startswith("/indiv/ws"):
            print(f"🔄 WebSocket 连接，跳过认证: {path}")
            response = await call_next(request)
            return response

        # 非白名单路径，需要验证 Token
        print(f"🔐 非白名单路径，需要验证 Token: {path}")
        # 从请求头中获取 Authorization
        auth_header = request.headers.get("Authorization")
        print(f"📋 Authorization 头: {auth_header}")

        if not auth_header:
            print("❌ 未提供 Token，返回 401")
            return JSONResponse(
                status_code=status.HTTP_401_UNAUTHORIZED,
                content={
                    "detail": "未提供认证令牌",
                    "code": 401
                },
                headers={"WWW-Authenticate": "Bearer"}
            )

        # 检查格式是否为 "Bearer <token>"
        parts = auth_header.split()
        if len(parts) != 2 or parts[0].lower() != "bearer":
            return JSONResponse(
                status_code=status.HTTP_401_UNAUTHORIZED,
                content={
                    "detail": "认证令牌格式错误",
                    "code": 401
                },
                headers={"WWW-Authenticate": "Bearer"}
            )

        token = parts[1]

        # 验证 Token
        payload = verify_token(token, token_type="access")
        if payload is None:
            return JSONResponse(
                status_code=status.HTTP_401_UNAUTHORIZED,
                content={
                    "detail": "Token 无效或已过期",
                    "code": 401
                },
                headers={"WWW-Authenticate": "Bearer"}
            )

        # Token 验证成功，将用户信息存入请求状态中，方便后续使用
        request.state.user = payload

        # 继续处理请求
        response = await call_next(request)
        return response
